package com.yangchuang.openpicture.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yangchuang.openpicture.constant.PictureStatisticsRedisConstants;
import com.yangchuang.openpicture.mapper.PictureStatisticsMapper;
import com.yangchuang.openpicture.pojo.PictureStatistics;
import com.yangchuang.openpicture.service.PictureStatisticsService;
import com.yangchuang.openpicture.util.RedisUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import static com.yangchuang.openpicture.util.ShanghaiTimeUtils.getCurrentTimeStr;

/**
 * 图片统计服务实现类
 * <p>
 * 该服务负责维护图片的统计数据，包括浏览量、点赞数、收藏数、下载数、评论数等。
 * 使用Redis作为缓存层，提高性能，并定期同步到MySQL数据库。
 *
 * @author naiyi
 * @version 1.0
 * @since 2025-09-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PictureStatisticsServiceImpl extends ServiceImpl<PictureStatisticsMapper, PictureStatistics> implements PictureStatisticsService {

    private final RedisUtils redisUtils;

    @Override
    public void PictureStatsHashUpdate(Long pictureId, Boolean isLike, Boolean isFavorite, Boolean isComment, Boolean isDownload) {
        //去找有没有 放的时候怎么放 找的时候就怎么找
        String key = PictureStatisticsRedisConstants.PICTURE_STATS_HASH + pictureId;
        //初始化的话(不存在)： 现在第一次被某张行为触发--》初始化了  浏览量设为1 （从0+1） 然后对应字段设置为1（从之前的状态（没有的话默认是0）+1）（判断传入的参数）
        //变动的话(已经存在)： 对应的字段+1/-1  浏览量+1
        //上述二者有共同点 ：  把设为1 理解成 1=0+1 不存在的话 会默认创建 所以说抽象出来的共同点就是 浏览量+1  还有就是
        //下面三件事是两种情况都会做的
        redisUtils.hashOps().incrementFieldBy(key, PictureStatisticsRedisConstants.PICTURE_STATS_HASH_FIELD_VIEWS_COUNT, 1);
        redisUtils.hashOps().setFieldValue(key, PictureStatisticsRedisConstants.PICTURE_STATS_HASH_FIELD_UPDATE_TIME, getCurrentTimeStr());
        //不用担心 因为如果真的是初始化的话 对应的字段一定是 不=null且为true 所以肯定是0+1变成1  且自动创建了这个字段
        //todo 唯一的问题可能是 如果真的是初始化 使用懒加载 某些field此时不会被创建（出生） 后续第一次被对应的操作的时候 才会出生
        // 同步的时候 如果这个key对应的字段 还没出生 代表 从没被对应的操作过 数据库里面设为0
        //喜欢数量
        if (isLike != null) {
            //进来是 true or false
            redisUtils.hashOps().incrementFieldBy(key, PictureStatisticsRedisConstants.PICTURE_STATS_HASH_FIELD_LIKES_COUNT, isLike ? 1 : -1);
        }
        //收藏数量 可多可少
        if (isFavorite != null) {
            redisUtils.hashOps().incrementFieldBy(key, PictureStatisticsRedisConstants.PICTURE_STATS_HASH_FIELD_FAVORITES_COUNT, isFavorite ? 1 : -1);
        }
        //评论数量 可多可少
        if (isComment != null) {
            redisUtils.hashOps().incrementFieldBy(key, PictureStatisticsRedisConstants.PICTURE_STATS_HASH_FIELD_COMMENTS_COUNT, isComment ? 1 : -1);
        }
        //下载量 只多不少
        if (isDownload != null) {
            redisUtils.hashOps().incrementFieldBy(key, PictureStatisticsRedisConstants.PICTURE_STATS_HASH_FIELD_DOWNLOADS_COUNT, 1);
        }
        //得分 后续会通过任务计算  这里不能直接设置成 因为可能会把之前算出来的重新设置成0  万一下一秒就同步到数据库了呢？
        //但是可以通过setFieldValueIfAbsent来排除掉上面那种情况 存在的话 其实下面就相当于不执行
        redisUtils.hashOps().setFieldValueIfAbsent(key, PictureStatisticsRedisConstants.PICTURE_STATS_HASH_FIELD_SCORE, 0);
        //脏数据？？ 不管是首次创建 还是更新了 string-set结构
        //变成脏数据了 ，主动上报
        //且 不能设置过期时间
        redisUtils.setOps().addMembers(PictureStatisticsRedisConstants.PICTURE_STATS_DIRTY_SET, pictureId);
    }

}
